package org.goldenmock.web.server;

import com.google.common.collect.Maps;
import org.mortbay.jetty.Server;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Map;

/**
 * The HttpServerWrapper constructs a server, injects a HttpRequestHandler, and
 * fires it up. It also keeps track of all server-instances that have been
 * started by calling create(port).
 * <p/>
 * Extra information: Every server uses a single HttpRequestHandler which is
 * called whenever a request is received. The HttpRequestHandler translates the
 * HttpServletRequest into an EasyHttpRequest, and passes it on to its delegate.
 * This delegate is just a regular mock (of the HttpServerInterface), on which
 * "the user" has defined certain expectations.
 *
 * @author Robin Wagenaar
 * @author Arjen van Staalduinen
 */
public final class HttpServerWrapper extends Server {
    private static Logger logger = LoggerFactory.getLogger(HttpServerWrapper.class);
    private static Map<Integer, HttpServerWrapper> runningInstances = Maps.newHashMap();

    /**
     * Constructs a mock-http-server and starts it. Also keeps track of
     * all running instances.
     */
    public static HttpServerInterface create(Integer port) {
        logger.info("creating on port {}", port);
        try {
            HttpServerWrapper wrapper = new HttpServerWrapper(port);
            HttpEasymockServer server = new HttpEasymockServer();
            wrapper.setHandler(server);
            wrapper.start();
            logger.debug("MockServer started on port [{}]", port);
            runningInstances.put(port, wrapper);
            return server.getMock();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * Searches the mock-http-server in the list of running instances
     * and kills it gracefully so that the port may be reused.
     */
    public static void kill(Integer port) {
        try {
            if (runningInstances.containsKey(port)) {
                runningInstances.get(port).stop();
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    private HttpServerWrapper(int port) {
        super(port);
    }

    void setHandler(HttpServerInterface delegate) {
        super.setHandler(new HttpRequestHandler(delegate));
    }
}
